//
//  SolarSeekEngine.m
//  SolarSeek
//
//  Created by Erick Fejta on 05/03/10.
//  Copyright 2005 Erick Fejta. All rights reserved.
//

#import "SolarSeekEngine.h"

#import "ConnectionsIdentifier.h"
#import "Connections.h"
#import "ServerConnectionController.h"
#import "PeersController.h"
#import "PeerConnectionsController.h"
#import "ShareController.h"
#import "SearchesController.h"
#import "TransfersController.h"
#import "ChatsController.h"
#import "Message.h"

@implementation SolarSeekEngine

- (id)init {
	if(self = [super init]) {
	
		_messagesServer = [[NSMutableArray alloc] init];
		_connectionsIdentifier = nil;
		_serverConnection = nil;
		_serverConnectionController = nil;
		_peersController = nil;
		_peerConnectionsController = nil;
		_shareController = nil;
		_searchesController = nil;
		_transfersController = nil;
		
		_connectionsIdentifier = [[ConnectionsIdentifier alloc] init];
		NSAssert(_connectionsIdentifier != nil,@"Could not create the ConnectionsIdentifier.");
		_serverConnection = [[ServerConnection alloc] init];
		NSAssert(_serverConnection != nil,@"Could not create the ServerConnection.");
		_serverConnectionController = [[ServerConnectionController alloc] initWithEngine:self];
		NSAssert(_serverConnectionController != nil,@"Could not create the ServerConnectionController.");
		_peersController = [[PeersController alloc] initWithEngine:self];
		NSAssert(_peersController != nil,@"Could not create the PeersController.");
		_peerConnectionsController = [[PeerConnectionsController alloc] initWithEngine:self];
		NSAssert(_peerConnectionsController != nil,@"Could not create the PeerConnectionsController.");
		_shareController = [[ShareController alloc] initWithEngine:self];
		NSAssert(_shareController != nil,@"Could not create the ShareController.");
		_searchesController = [[SearchesController alloc] initWithEngine:self];
		NSAssert(_searchesController != nil,@"Could ont create the SearchesController.");
		_transfersController = [[TransfersController alloc] initWithEngine:self];
		NSAssert(_transfersController != nil,@"Could not create the TransfersController.");
		_chatsController = [[ChatsController alloc] initWithEngine:self];
		NSAssert(_chatsController != nil,@"Could not create the ChatsController.");
		//fejta: TODO: medium: handle these assertions.
		
		//fejta: TODO: medium: serverConnection should be an aspect of the ServerConnection controller!
		//[[self me] retain];
	}
	return self;
}

- (void)dealloc {
	[_messagesServer release];
	[_connectionsIdentifier release];
	[_peerConnectionsController release];
	[_peersController release];
	[_searchesController release];
	[_serverConnection release];
	[_serverConnectionController release];
	[_shareController release];
	[_transfersController release];
	[_chatsController release];
	[[self me] release];
	[super dealloc];
}

#pragma mark KVO

- (ConnectionsIdentifier *)connectionsIdentifier { 
	NSAssert(_connectionsIdentifier!=nil,@"The connections identifier has not been initialized.");
	return _connectionsIdentifier; 
}

- (PeerConnectionsController *)peerConnectionsController { 
	NSAssert(_peerConnectionsController!=nil,@"The peer connections controller has not been initialized.");
	return _peerConnectionsController; 
}

- (PeersController *)peersController { 
	NSAssert(_peersController!=nil,@"The peers controller has not been initialized.");
	return _peersController; 
}

- (SearchesController *)searchesController {
	NSAssert(_searchesController!=nil,@"The searches controller has not been initialized.");
	 return _searchesController; 
}

- (ServerConnection *)serverConnection { 
	NSAssert(_serverConnection!=nil,@"The server connection has not been initialized.");
	return _serverConnection; 
}

- (ServerConnectionController *)serverConnectionController {
	NSAssert(_serverConnectionController!=nil,@"The server connection controller has not been initialized.");
	return _serverConnectionController;
}

- (ShareController *)shareController { 
	NSAssert(_shareController!=nil,@"The share controller has not been initialized.");
	return _shareController; 
}

- (TransfersController *)transfersController { 
	NSAssert(_transfersController!=nil,@"The transfers controller has not been initialized.");
	return _transfersController; 
}

- (ChatsController *)chatsController { 
	NSAssert(_chatsController!=nil,@"The chats controller has not been initialized.");
	return _chatsController; 
}

- (void)updateStatusPeer:(Peer *)peer {
	[[self peersController] sendTrackingMessageForPeer:peer];
}

- (void)watchPeer:(Peer *)peer {
	[[self peersController] trackAvailabilityForPeer:peer];
}

- (void)stopWatchingPeer:(Peer *)peer {
	[[self peersController] stopTrackingAvailabilityForPeer:peer];
}

- (void)getBuddyIconForPeer:(Peer *)peer {
	Message *m = [Message messageWithCode:QuestionBuddyIcon];
	[[[self peerConnectionsController] peerConnectionForPeer:peer] sendMessage:m];
}
	
- (Peer *)me {
	if(_me==nil) {
		NSString *u = [_serverConnectionController username]; 
		u=(u?u:[[NSUserDefaults standardUserDefaults] stringForKey:SolarSeekDefaultUsername]);
		u=(u?u:@"");
		_me = [[Peer alloc] initWithName:u];
	}
	return _me;
}

- (Peer *)peerNamed:(NSString *)name {
	return [_peersController peerForName:name];
}

#pragma mark actions

- (void)send {
	[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(send) object:nil];
	if([_serverConnectionController loggedIn]) {
		NSEnumerator *e = [_messagesServer objectEnumerator];
		Message *m;
		while(m = [e nextObject]) 
			[_serverConnection sendMessage:m];
		[_messagesServer removeAllObjects];
	}
	else
		[self performSelector:@selector(send) withObject:nil afterDelay:0.5];
}

- (void)sendServerMessage:(Message *)message {
	[self performSelectorOnMainThread:@selector(sendServerMessageOnMainThread:) withObject:message waitUntilDone:NO];
}

- (void)sendServerMessageOnMainThread:(Message *)message {
	[_messagesServer addObject:message];
	[self performSelector:@selector(send) withObject:nil afterDelay:0.01];
	[_messagesServer performSelector:@selector(removeObject:) withObject:message afterDelay:60.0];
}

- (void)setAvailability:(Availability)availability {
	[[self me] setAvailability:availability];
	if([[self serverConnectionController] loggedIn]) {
		Message *m = [Message messageWithCode:SetStatus];
		[m putInt:availability];
		[self sendServerMessage:m];
	}
}

- (unsigned)tokenNext {	return [[self serverConnection] tokenNext]; }

@end
